/**
 * @file random_module_generator.c
 * @brief function definitions for generating random modules
 * @author Scott Moyers
 * @date 2009
 */

#include "random_module_generator.h"
#include "util.h"

/**
 * picks a random number [0, n)
 * biased towards numbers closer to n
 * @param dsfmt the random number generator
 * @param n number of possible sources
 * @return a random number from [0 n)
 */
static int random_input_biased(dsfmt_t *dsfmt, int n)
{
	int r = (int) (dsfmt_genrand_close_open(dsfmt) * sum_of_1_n(n- 1));
	int i = 0;
	int cnt = 0;
	while(cnt < r) {
		i++;
		cnt += i;
	}
	return i;
}


/**
 * picks a random input
 * @param dsfmt the random number generator
 * @param n number of possible sources
 * @return a random number from [0 n)
 */
static int random_input(dsfmt_t *dsfmt, int n)
{
	/* pick input distribution randomly */
	if (dsfmt_genrand_close_open(dsfmt) < 0.5) {
		return random_input_biased(dsfmt, n);
	} else {
		return (int) (dsfmt_genrand_close_open(dsfmt) * n);
	}
}

struct Module *rand_module(dsfmt_t *dsfmt, int id, int num_inputs, int num_gates)
{
	int i;
	struct Module *m = new_module(id, num_inputs, num_gates);
	for(i = 0; i < num_gates; i++) {
		struct Gate *g = &m->circuit[i];
		g->colour = WHITE;
		g->gate_type = (int) (dsfmt_genrand_close_open(dsfmt) * GATE_TYPES);
		g->in[0] = random_input(dsfmt, num_inputs + i);
		g->in[1] = random_input(dsfmt, num_inputs + i);
		g->out = num_inputs + i;
	}
	return m;
}
